<html>
<head>
<title>CpcPaChi - Version 0.07</title>
<style type="text/css">
span {
	font-family: 'Courier New';
	font-size: 10pt;
	color: #000000;
}
.sc0 {
	color: #808080;
}
.sc3 {
	color: #008080;
}
.sc4 {
	color: #FF8000;
}
.sc5 {
	font-weight: bold;
	color: #0000FF;
}
.sc7 {
	color: #808080;
}
.sc9 {
	color: #804000;
}
.sc10 {
	font-weight: bold;
	color: #000080;
}
.sc11 {
}
</style>
</head>
<body>
<h2>Un compilador sencillo paso a paso (7 - Primera tabla de s&iacute;mbolos)</h2>

<p align="right">(Volver al <a href="doc.html">&iacute;ndice</a>) </p>

<p>Los programas que reconoce nuestro compilador pueden tener instrucciones con o sin par&aacute;metros, pero hasta ahora esos par&aacute;metros s&oacute;lo pueden ser n&uacute;meros. En el "mundo real" esto no es as&iacute;, es muy frecuente necesitar trabajar con valores cambiantes, que se almacenar&aacute;n en variables.</p>

<p>Como primer acercamiento, vamos a hacer que nuestro compilador sea capaz de reconocer constantes, y en la pr&oacute;xima entrega ampliaremos para que tambi&eacute;n sean variables.</p>

<p>Existen distintos tipos de datos. Como nuestra m&aacute;quina de destino tiene un procesador de 8 bits, por ahora usaremos el m&aacute;s sencillo para nosotros: un tipo de datos Byte, que ocupe 1 byte en memoria y pueda almacenar un n&uacute;mero entero con un valor entre 0 y 255. Es algo limitado, pero que nos permitir&aacute; hacer proyectos peque&ntilde;os.</p>

<p>De cada constante necesitaremos varios datos: el nombre, el tipo de datos (por ahora s&oacute;lo "byte") y su valor. M&aacute;s adelante necesitaremos otros datos parecidos de cada variable (pero no guardaremos su valor actual, sino la direcci&oacute;n de memoria en que &eacute;ste se encuentra) y de cada funci&oacute;n.</p>

<p>Permitiremos que se pueda declarar varias constantes, separadas por comas. Todas tendr&aacute;n la forma "nombre = valor", comenzar&aacute;n con la palabra "const" y terminar&aacute;n con un punto y coma, de modo que un program sencillo podr&iacute;a ser as&iacute;:</p>

<pre><code>
program ej;
const linea = 10, columnaA = 10, columnaB = 1;
begin
  cpcMode(0);
  pen(2);
  paper(1);
  locate(columnaA, linea);
  writeChar( 'a' );
  pen(4);
  paper(3);
  locate ( columnaB ,  linea );
  writeChar('c');
end.
</code></pre>

<p>Cuando el analizador sint&aacute;ctico encuentre la palabra "const", deber&aacute; guardar informaci&oacute;n sobre la constante que se le indique (o las constantes, si son varias). Para ello, dentro del generador de c&oacute;digo crearemos una funci&oacute;n "insertarSimboloConst", que recibir&aacute; dos par&aacute;metros: el nombre y el valor, y una segunda funci&oacute;n "leerSimboloConst", que recibir&aacute; el nombre de la constante y devolver&aacute; su valor. Nuestra tabla de s&iacute;mbolos ser&aacute; rudimentaria: para no perder tiempo en crear estructuras de datos m&aacute;s eficientes, ser&aacute; simplemente un "array" de registros. Por tanto, para insertar un s&iacute;mbolo, recorreremos este array, a&ntilde;adiendo al final, o dando un mensaje de error si el s&iacute;mbolo est&aacute; repetido:</p>

<pre><code>
(* Guardar una constante en la tabla de símbolos *)
procedure insertarSimboloConst(nombreConst: string; valorConst: string);
var
  i: integer;
begin
  nombreConst := upcase(nombreConst);
  (* Primero comprobamos si el simbolo ya existe *)
  for i:=1 to numSimbolos do
    if listaSimbolos[i].nombre = nombreConst then
      begin
        writeln('Constante repetida!');
        halt;
      end;
  (* Si no existe, lo insertamos *)
  numSimbolos := numSimbolos + 1;
  listaSimbolos[numSimbolos].nombre := nombreConst;
  listaSimbolos[numSimbolos].tipoDato := tBYTE;
  listaSimbolos[numSimbolos].valorDir := valorConst;
end;
</code></pre>


<p>Para leer un s&iacute;mbolo de nuestra tabla de s&iacute;mbolos sencilla, recorremos el array, y damos un mensaje en caso de que no exista:</p>

<pre><code>
(* Leer una constante de la tabla de símbolos *)
function leerSimboloConst(nombreConst: string): byte;
var
  encontrado: boolean;
  i: integer;
  x: byte;
  codError: integer;
begin
  nombreConst := upcase(nombreConst);
  encontrado := false;
  (* Primero comprobamos si el simbolo ya existe *)
  for i:=1 to numSimbolos do
    begin
    if listaSimbolos[i].nombre = nombreConst then
      begin
        val(listaSimbolos[i].valorDir, x, codError);
        leerSimboloConst := x;
        encontrado := true;
      end;
    end;
  (* Si no existe, mensaje de error *)
  if encontrado = false then
      begin
        writeln('Constante inexistente!');
        halt;
      end;
end;
</code></pre>


<p>Ahora deber&iacute;amos modificar ligeramente las funciones que antes esperaban un par&aacute;metro num&eacute;rico, como CpcMode, para que esta vez reciban un identificador o un n&uacute;mero, si se trata de un identificador, deberemos buscar su valor en la tabla de s&iacute;mbolos. Lo podr&iacute;amos hacer as&iacute;:</p>

<pre><code>
procedure analizarCPCMODE;
begin
  leerSimbolo('(');

  cadenaTemp := obtenerEnteroOIdentificador;
  if cadenaTemp[1] in ['a'..'z'] then
    x := leerSimboloConst(cadenaTemp)
  else
    val(cadenaTemp,x,codError);

  leerSimbolo(')');
  leerSimbolo(';');
  genCPCMODE(x);
end;
</code></pre>

<p>Con pocos cambios similares a ese, conseguir&iacute;amos que nuestro mini-compilador reconozca tanto valores num&eacute;ricos como constantes.</p>

<p><br>Como siempre, para m&aacute;s detalles, todo el c&oacute;digo est&aacute; en la p&aacute;gina del proyecto en Google Code:<br /><br /><a href="http://code.google.com/p/cpcpachi/">http://code.google.com/p/cpcpachi/</a></p>

<p align="right">(Volver al <a href="doc.html">&iacute;ndice</a>) </p>
</body>
</html>
